<?php
    
    class ForumHandler{
    	
		private $_topicsTableName = "topics";
		private $_postsTableName = "posts";
		private $_categoriesTableName = "categories";
		private $_usersTableName ="users";
		private $_dbconnection = null;
		private $_privateMessageTableName = "privmess";
		
		public function __construct(DBConnection $aDBConnection){
			$this->_dbconnection = $aDBConnection;
		}
		//Function to retrieve all categories in the database. Returns an array of Categories
		public function GetAllCategories(){
			
			$sql = "SELECT * FROM $this->_categoriesTableName";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Category", "_id");
			
			return $ret;
		}
		//Function to retrieve all topics from a specific category. Returns an array of Topics
		public function GetAllTopicsFromCategory($categoryid)
		{
			$sql = "SELECT * FROM $this->_topicsTableName WHERE _categoryid = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $categoryid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Topic", "_id");
			
			return $ret;
		}
		//Function to get all posts from a specific Topic. Returns an array of Posts
		public function GetAllPostsFromTopic($topicid){
			
			$sql = "SELECT * FROM $this->_postsTableName WHERE _topicid = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $topicid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Post", "_id");
			
			return $ret;
		}
		//Function to retrieve a Topic with a specific id. Returns a Topic.
		public function GetTopicFromId($topicid){
			
			$sql = "SELECT * FROM $this->_topicsTableName WHERE _id = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $topicid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Topic", "_id");
			
			return $ret[$topicid];
				
		}
		//Function to find out which id a topic with a specific name has. Returns an int with the id.
		public function GetTopicIdFromName($topicName){
			
			$sql = "SELECT * FROM $this->_topicsTableName WHERE _name = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("s", $topicName);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Topic", "_name");
			
			return $ret[$topicName]->_id;
		}
		//Function to retrieve the message from a specific post. Returns a string with the message.
		public function GetPostMessageFromId($postid){
			
			$sql = "SELECT * FROM $this->_postsTableName WHERE _id = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $postid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Post", "_id");
			
			return $ret[$postid]->_message;
		}
		//Function to retrieve a category with a specific ID. Returns a Category Object
		public function GetCategoryFromId($categoryid){
			
			$sql = "SELECT * FROM $this->_categoriesTableName WHERE _id = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $categoryid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Category", "_id");
			
			return $ret[$categoryid];
		}
		//Function to retrieve all messages that a specific user have sent. Returns an array of Privmess
		public function GetSentPrivateMessagesFromUser($username)
		{
			$sql = "SELECT * FROM $this->_privateMessageTableName WHERE _sender= ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("s", $username);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "PrivMess", "_id");
			
			return $ret;
		}
		//Function to retrieve all messages that a specific user have received. Returns an array of Privmess
		public function GetRecievedPrivateMessagesFromUser($username)
		{
			$sql = "SELECT * FROM $this->_privateMessageTableName WHERE _receiver = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("s", $username);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "PrivMess", "_id");

			return $ret;
		}
		//Function to retrieve a specific Private Message. Returns said message
		public function GetPrivateMessageFromId($messageid)
		{
			$sql = "SELECT * FROM $this->_privateMessageTableName WHERE _id = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("i", $messageid);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "PrivMess", "_id");

			return $ret[$messageid];
		}
		//Function to retrieve the last post made in a specific Topic. Returns a Post
		public function GetLastPostFromTopic($topicid){
			
			$arrayOfPosts = $this->GetAllPostsFromTopic($topicid);
			$arrayOfTimes = null;
			
			foreach($arrayOfPosts as $post)
			{
				$arrayOfTimes[$post->_id] = $post->_time;
			}
			
			asort($arrayOfTimes);
			
			$idOfLastPost = key(array_slice($arrayOfTimes, -1, null, true));
			
			return $arrayOfPosts[$idOfLastPost];
		}
		//Function to retrieve the last post made in a specific category. Returns a Post
		public function GetLastPostFromCategory($categoryid){
			
			$arrayOfTopics = $this->GetAllTopicsFromCategory($categoryid);
			$arrayOfLastPosts = null;
			$arrayOfLastPostsTimes = null;
			
			foreach($arrayOfTopics as $topic){
				$lastPost = $this->GetLastPostFromTopic($topic->_id);
				$arrayOfLastPosts[$lastPost->_id] = $lastPost;
				$arrayOfLastPostsTimes[$lastPost->_id] = $lastPost->_time;
			}
			
			asort($arrayOfLastPostsTimes);
					
			$idOfLastPost = key(array_slice($arrayOfLastPostsTimes, -1, null, true));
			
			return $arrayOfLastPosts[$idOfLastPost];
		}
		//Function to find out how many replies have been made to a specific topic. Returns an int with the number of replies
		public function GetNumberOfRepliesFromTopic($topicid){
			$arrayOfPosts = $this->GetAllPostsFromTopic($topicid);
			$numberOfReplies = count($arrayOfPosts) - 1;
			return $numberOfReplies;
		}
		//Function to find out how many topics exist in a specific category. Returns an int with the number of topics
		public function GetNumberOfTopicsFromCategory($categoryid){
			$arrayOfTopics = $this->GetAllTopicsFromCategory($categoryid);
			$numberOfTopics = count($arrayOfTopics);
			return $numberOfTopics;
		}
		//Function to discover which page a specific post is on. Returns an int with the page number
		public function GetWhichPagePostIsOn($topicid ,$postid){
			$arrayOfPosts = $this->GetAllPostsFromTopic($topicid);
			$postposition = null;
			
			foreach ($arrayOfPosts as $post) {
				if($post->_id == $postid){
					break;
				}
				else{
					$postposition += 1;
				}
			}
			$page = (int)($postposition / 10 ) + 1;

			return $page;
		}
		//Function to find out how many posts have been made in a specific category. Returns an int with the number of posts
		public function GetNumberOfPostsFromCategory($categoryid){
			
			$numberOfPosts = null;
			$arrayOfTopics = $this->GetAllTopicsFromCategory($categoryid);
			
			foreach ($arrayOfTopics as $topic ) {
				$posts = $this->GetNumberOfRepliesFromTopic($topic->_id);
				$numberOfPosts += $posts + 1;
			}
			return $numberOfPosts;
		}
		//Function to add a new Private Message. Returns true if succesful, and false if it doesn't validate.
		public function AddPrivateMessage($sender,$reciever,$message,$topic){
			
			//TODO CHECK IF RECIEVER EXISTS USER HANDLER QQ STUFF
			
			$message = Validate::StripAll($message);
			$topic = Validate::StripAll($topic);
			
			if(strlen($message) < 10){
				return FALSE;
			}
			if(strlen($topic) == 0){
				return FALSE;
			}
						
			$sql = "INSERT INTO $this->_privateMessageTableName VALUES(?,?,?,'',?,?)";
	        			
	        $aStatement = $this->_dbconnection->Prepare($sql);
			
			$null = NULL;
	      	$aStatement->bind_param('sssis',$sender,$reciever,$message,$null,$topic);
				
			$aStatement->execute();
			
			return true;
		}
		//Function to Add a new post to a specific topic. Returns true if succesful.
		public function AddNewPostToTopic($topicid, $username, $message){
			
			$message = Validate::StripAll($message);
			
			if(strlen($message) < 10){
				return FALSE;
			}
						
			$sql = "INSERT INTO $this->_postsTableName VALUES(?,?,?,?,'')";
	        			
	        $aStatement = $this->_dbconnection->Prepare($sql);
			
			$null = NULL;
	      	$aStatement->bind_param('siss', $username, $topicid, $message, $null);
				
			$aStatement->execute();
			
			$this->IncreasePostCount($username);
			return true;
		}
		//Function to remove a Post. Returns true if succesful
		public function RemovePost($postid){
			
			$sql = "DELETE FROM $this->_postsTableName WHERE _id = ?";
	                
	        $aStatement = $this->_dbconnection->Prepare($sql);
			
	      	$aStatement->bind_param("i", $postid);
				
			$aStatement->execute();
			
			return true;
		}
		//Function to remove a Topic. Returns true if succesful
		public function RemoveTopic($topicid){
			
			$sql = "DELETE FROM $this->_topicsTableName WHERE _id = ?";
	                
	        $aStatement = $this->_dbconnection->Prepare($sql);
			
	      	$aStatement->bind_param("i", $topicid);
				
			$aStatement->execute();
			
			return true;
		}
		//Function to check is a user made a specific post. Returns true if he did, otherwise false
		public function CheckIfUserMadePost($postid,$username){
			
			$sql = "SELECT * FROM $this->_postsTableName WHERE _username = ? AND _id = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("si", $username,$postid);
			
			$aStatement->execute();
			
			$result = $this->_dbconnection->RunAndFetchObjects($aStatement, "Post", "_id");
			
			if($result != null){
				return true;
			}
			return false;
		}
		//Function for change whether a topic is sticky or not. Returns true if succesful
		public function ChangeStickyForTopic($topicid)
		{
			$sql = "UPDATE $this->_topicsTableName SET _sticky = ((_sticky+1)%2) WHERE _id = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
            $aStatement->bind_param("i", $topicid);
			
			$aStatement->execute();
			
			return true;
		}
		//TODO MOVE THIS FUNCTION
		public function IncreasePostCount($username){
			
			$sql = "UPDATE $this->_usersTableName SET Postcount = Postcount + 1 WHERE Username = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
            $aStatement->bind_param("s", $username);
			
			$aStatement->execute();
			
			return true;
		}
		//TODO MOVE THIS FUNCTION
		public function ChangeUserImage($username, $newimage){
			
			$sql = "UPDATE $this->_usersTableName SET Image = ? WHERE Username = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
            $aStatement->bind_param("ss", $newimage, $username);
			
			$aStatement->execute();
			
			return true;
		}
		//TODO MOVE THIS FUNCTION
		public function GetPostCountFromUsername($username){
			
			$sql = "SELECT PostCount from $this->_usersTableName WHERE Username = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
			$aStatement->bind_param("s", $username);
			
			$aStatement->execute();
			
			$aStatement->bind_result($postcount);
			
			$aStatement->fetch();
			
			return $postcount;		
		}
		//TODO MOVE THIS FUNCTION
		public function GetImageFromUsername($username){
			
			$sql = "SELECT Image from $this->_usersTableName WHERE Username = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
			$aStatement->bind_param("s", $username);
			
			$aStatement->execute();
			
			$aStatement->bind_result($image);
			
			$aStatement->fetch();
			
			return $image;		
		}
		//TODO MOVE THIS FUNCTION
		public function CheckIfUserIsModerator($username){
			
			$sql = "SELECT IsModerator from $this->_usersTableName WHERE Username = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
			$aStatement->bind_param("s", $username);
			
			$aStatement->execute();
			
			$aStatement->bind_result($isadmin);
			
			$aStatement->fetch();
			
			return $isadmin;
		}
		
		// Function to Edit a Topic. Returns true is successful, otherwise returns false
		public function EditPost($postid,$newPostMessage){
			
			$message = Validate::StripAll($newPostMessage);
			
			if(strlen($newPostMessage) < 10){
				return FALSE;
			}
			
			$sql = "UPDATE $this->_postsTableName SET _message = ? WHERE _id = ?";
			
			$aStatement = $this->_dbconnection->Prepare($sql);
			
            $aStatement->bind_param("si", $newPostMessage,$postid);
			
			$aStatement->execute();
			
			return true;
		}
		
		// Function to Add a new Topic. Returns true is successful, otherwise returns false
		public function AddNewTopicToCategory($topicname,$username,$categoryid){
			
			$topicname = Validate::StripAll($topicname);
						
			if(strlen($topicname) == 0){
				return FALSE;
			}
			
			$sql = "INSERT INTO $this->_topicsTableName VALUES(?,?,?,'',0)";
	        			
	        $aStatement = $this->_dbconnection->Prepare($sql);
			
	      	$aStatement->bind_param('ssi', $username, $topicname, $categoryid);
				
			$aStatement->execute();
			
			return true;
		}
		
		// Function to upload a Image. Returns true is successful, otherwise returns false
		function UploadUserImage($file, $username) {
			
			$oldImage = $this->GetImageFromUsername($username);
			
			if ((($file["type"] == "image/png") 
			|| ($file["type"] == "image/jpeg") 
			|| ($file["type"] == "image/gif")) 
			&& ($file["size"] <1000000)) {
	
				if ($file["error"] > 0) {
					return false;
				} else {
					if (file_exists("UserImages/". $file["name"])) {
						return false;
					} else {
						
						if($oldImage != "default.png"){
							unlink("UserImages/$oldImage");
						}
						
						move_uploaded_file($file["tmp_name"], "UserImages/" . $file["name"]);
						$this->ChangeUserImage($username, $file["name"]);
						return true;
						
					}
				}
			}
			return false;
		}
		//NOT IMPLEMENTED.
		//Function to retrieve all posts a specific user have made. Returns an array of Posts
		public function GetAllPostsFromUser($username){
			$sql = "SELECT * FROM $this->_postsTableName WHERE _username = ?";
                
            $aStatement = $this->_dbconnection->Prepare($sql);
                
            $aStatement->bind_param("s", $username);
			
			$ret = $this->_dbconnection->RunAndFetchObjects($aStatement, "Post", "_id");
			
			return $ret;
		}
		//TEST
		public function Test()
		{
			
		}
    }
